package ynu.edu.dish.service.impl;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ynu.edu.common.exception.BusinessException;
import ynu.edu.dish.dto.DishDTO;
import ynu.edu.dish.dto.DishSpecDTO;
import ynu.edu.dish.entity.Dish;
import ynu.edu.dish.entity.DishCategory;
import ynu.edu.dish.repository.DishCategoryRepository;
import ynu.edu.dish.repository.DishRepository;
import ynu.edu.dish.service.DishService;
import ynu.edu.dish.service.DishSpecService;
import ynu.edu.dish.vo.DishSpecVO;
import ynu.edu.dish.vo.DishVO;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜品服务实现类
 */
@Service
@RequiredArgsConstructor
public class DishServiceImpl implements DishService {

    private final DishRepository dishRepository;
    private final DishCategoryRepository dishCategoryRepository;
    private final DishSpecService dishSpecService;

    @Override
    @Transactional
    public DishVO createDish(DishDTO dishDTO) {
        // 检查菜品分类是否存在
        DishCategory dishCategory = dishCategoryRepository.findById(dishDTO.getCategoryId())
                .orElseThrow(() -> new BusinessException("菜品分类不存在"));

        // 创建新的菜品
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);

        // 保存菜品
        dish = dishRepository.save(dish);

        // 保存菜品规格
        List<DishSpecDTO> specDTOs = dishDTO.getSpecs();
        List<DishSpecVO> specVOs = null;
        if (specDTOs != null && !specDTOs.isEmpty()) {
            // 设置菜品ID
            final Long dishId = dish.getId(); // 创建一个final变量存储dish.getId()
            specDTOs.forEach(spec -> spec.setDishId(dishId)); // 使用final变量
            // 批量创建菜品规格
            specVOs = dishSpecService.batchCreateDishSpecs(specDTOs);
        }

        // 转换为VO并返回
        DishVO dishVO = convertToVO(dish);
        dishVO.setCategoryName(dishCategory.getName());
        dishVO.setSpecs(specVOs);
        return dishVO;
    }

    @Override
    @Transactional
    public DishVO updateDish(DishDTO dishDTO) {
        // 检查菜品是否存在
        Dish dish = dishRepository.findById(dishDTO.getId())
                .orElseThrow(() -> new BusinessException("菜品不存在"));

        // 检查菜品分类是否存在
        DishCategory dishCategory = dishCategoryRepository.findById(dishDTO.getCategoryId())
                .orElseThrow(() -> new BusinessException("菜品分类不存在"));

        // 更新菜品
        BeanUtils.copyProperties(dishDTO, dish);

        // 保存菜品
        dish = dishRepository.save(dish);

        // 更新菜品规格
        List<DishSpecDTO> specDTOs = dishDTO.getSpecs();
        List<DishSpecVO> specVOs = null;
        if (specDTOs != null) {
            // 删除原有规格
            dishSpecService.deleteAllByDishId(dish.getId());
            
            if (!specDTOs.isEmpty()) {
                // 设置菜品ID
                final Long dishId = dish.getId(); // 创建一个final变量存储dish.getId()
                specDTOs.forEach(spec -> spec.setDishId(dishId)); // 使用final变量
                // 批量创建菜品规格
                specVOs = dishSpecService.batchCreateDishSpecs(specDTOs);
            }
        } else {
            // 查询原有规格
            specVOs = dishSpecService.getDishSpecsByDishId(dish.getId());
        }

        // 转换为VO并返回
        DishVO dishVO = convertToVO(dish);
        dishVO.setCategoryName(dishCategory.getName());
        dishVO.setSpecs(specVOs);
        return dishVO;
    }

    @Override
    public DishVO getDishById(Long id) {
        // 查询菜品
        Dish dish = dishRepository.findById(id)
                .orElseThrow(() -> new BusinessException("菜品不存在"));

        // 查询菜品分类
        DishCategory dishCategory = dishCategoryRepository.findById(dish.getCategoryId())
                .orElse(null);

        // 查询菜品规格
        List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(id);

        // 转换为VO并返回
        DishVO dishVO = convertToVO(dish);
        if (dishCategory != null) {
            dishVO.setCategoryName(dishCategory.getName());
        }
        dishVO.setSpecs(specVOs);
        return dishVO;
    }

    @Override
    @Transactional
    public boolean deleteDish(Long id) {
        // 检查菜品是否存在
        if (!dishRepository.existsById(id)) {
            throw new BusinessException("菜品不存在");
        }

        // 删除菜品规格
        dishSpecService.deleteAllByDishId(id);

        // 删除菜品
        dishRepository.deleteById(id);

        return true;
    }

    @Override
    public List<DishVO> getDishesByMerchantId(Long merchantId) {
        // 查询菜品列表
        List<Dish> dishes = dishRepository.findByMerchantId(merchantId);

        // 转换为VO列表并返回
        return dishes.stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    // 查询菜品分类
                    DishCategory dishCategory = dishCategoryRepository.findById(dishVO.getCategoryId())
                            .orElse(null);
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<DishVO> getDishesByMerchantIdAndStatus(Long merchantId, Integer status) {
        // 查询菜品列表
        List<Dish> dishes = dishRepository.findByMerchantIdAndStatus(merchantId, status);

        // 转换为VO列表并返回
        return dishes.stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    // 查询菜品分类
                    DishCategory dishCategory = dishCategoryRepository.findById(dishVO.getCategoryId())
                            .orElse(null);
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<DishVO> getDishesByCategoryId(Long categoryId) {
        // 查询菜品列表
        List<Dish> dishes = dishRepository.findByCategoryId(categoryId);

        // 查询菜品分类
        DishCategory dishCategory = dishCategoryRepository.findById(categoryId)
                .orElse(null);

        // 转换为VO列表并返回
        return dishes.stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<DishVO> getDishesByCategoryIdAndStatus(Long categoryId, Integer status) {
        // 查询菜品列表
        List<Dish> dishes = dishRepository.findByCategoryIdAndStatus(categoryId, status);

        // 查询菜品分类
        DishCategory dishCategory = dishCategoryRepository.findById(categoryId)
                .orElse(null);

        // 转换为VO列表并返回
        return dishes.stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());
    }

    @Override
    public Page<DishVO> getDishesByMerchantId(Long merchantId, int page, int size) {
        // 创建分页请求
        PageRequest pageRequest = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createTime"));

        // 查询菜品分页列表
        Page<Dish> dishPage = dishRepository.findByMerchantId(merchantId, pageRequest);

        // 转换为VO分页列表并返回
        List<DishVO> dishVOs = dishPage.getContent().stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    // 查询菜品分类
                    DishCategory dishCategory = dishCategoryRepository.findById(dishVO.getCategoryId())
                            .orElse(null);
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());

        return new PageImpl<>(dishVOs, pageRequest, dishPage.getTotalElements());
    }

    @Override
    public Page<DishVO> getDishesByCategoryId(Long categoryId, int page, int size) {
        // 创建分页请求
        PageRequest pageRequest = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createTime"));

        // 查询菜品分页列表
        Page<Dish> dishPage = dishRepository.findByCategoryId(categoryId, pageRequest);

        // 查询菜品分类
        DishCategory dishCategory = dishCategoryRepository.findById(categoryId)
                .orElse(null);

        // 转换为VO分页列表并返回
        List<DishVO> dishVOs = dishPage.getContent().stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());

        return new PageImpl<>(dishVOs, pageRequest, dishPage.getTotalElements());
    }

    @Override
    public Page<DishVO> searchDishesByName(String name, int page, int size) {
        // 创建分页请求
        PageRequest pageRequest = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createTime"));

        // 查询菜品分页列表
        Page<Dish> dishPage = dishRepository.findByNameContaining(name, pageRequest);

        // 转换为VO分页列表并返回
        List<DishVO> dishVOs = dishPage.getContent().stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    // 查询菜品分类
                    DishCategory dishCategory = dishCategoryRepository.findById(dishVO.getCategoryId())
                            .orElse(null);
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());

        return new PageImpl<>(dishVOs, pageRequest, dishPage.getTotalElements());
    }

    @Override
    public Page<DishVO> searchDishesByMerchantIdAndName(Long merchantId, String name, int page, int size) {
        // 创建分页请求
        PageRequest pageRequest = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createTime"));

        // 查询菜品分页列表
        Page<Dish> dishPage = dishRepository.findByMerchantIdAndNameContaining(merchantId, name, pageRequest);

        // 转换为VO分页列表并返回
        List<DishVO> dishVOs = dishPage.getContent().stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    // 查询菜品分类
                    DishCategory dishCategory = dishCategoryRepository.findById(dishVO.getCategoryId())
                            .orElse(null);
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());

        return new PageImpl<>(dishVOs, pageRequest, dishPage.getTotalElements());
    }

    @Override
    @Transactional
    public boolean updateDishStatus(Long id, Integer status) {
        // 检查菜品是否存在
        Dish dish = dishRepository.findById(id)
                .orElseThrow(() -> new BusinessException("菜品不存在"));

        // 更新状态
        dish.setStatus(status);
        dishRepository.save(dish);

        return true;
    }

    @Override
    @Transactional
    public boolean updateDishRecommendedStatus(Long id, Integer isRecommended) {
        // 检查菜品是否存在
        Dish dish = dishRepository.findById(id)
                .orElseThrow(() -> new BusinessException("菜品不存在"));

        // 更新推荐状态
        dish.setIsRecommended(isRecommended);
        dishRepository.save(dish);

        return true;
    }

    @Override
    @Transactional
    public boolean updateDishSpecialStatus(Long id, Integer isSpecial, Double specialPrice) {
        // 检查菜品是否存在
        Dish dish = dishRepository.findById(id)
                .orElseThrow(() -> new BusinessException("菜品不存在"));

        // 更新特价状态
        dish.setIsSpecial(isSpecial);
        if (isSpecial == 1 && specialPrice != null) {
            dish.setSpecialPrice(BigDecimal.valueOf(specialPrice));
        } else {
            dish.setSpecialPrice(null);
        }
        dishRepository.save(dish);

        return true;
    }

    @Override
    public List<DishVO> getRecommendedDishesByMerchantId(Long merchantId) {
        // 查询推荐菜品列表
        List<Dish> dishes = dishRepository.findByMerchantIdAndIsRecommended(merchantId, 1);

        // 转换为VO列表并返回
        return dishes.stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    // 查询菜品分类
                    DishCategory dishCategory = dishCategoryRepository.findById(dishVO.getCategoryId())
                            .orElse(null);
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<DishVO> getSpecialDishesByMerchantId(Long merchantId) {
        // 查询特价菜品列表
        List<Dish> dishes = dishRepository.findByMerchantIdAndIsSpecial(merchantId, 1);

        // 转换为VO列表并返回
        return dishes.stream()
                .map(this::convertToVO)
                .peek(dishVO -> {
                    // 查询菜品分类
                    DishCategory dishCategory = dishCategoryRepository.findById(dishVO.getCategoryId())
                            .orElse(null);
                    if (dishCategory != null) {
                        dishVO.setCategoryName(dishCategory.getName());
                    }
                    // 查询菜品规格
                    List<DishSpecVO> specVOs = dishSpecService.getDishSpecsByDishId(dishVO.getId());
                    dishVO.setSpecs(specVOs);
                })
                .collect(Collectors.toList());
    }

    /**
     * 将实体转换为VO
     *
     * @param dish 菜品实体
     * @return 菜品VO
     */
    private DishVO convertToVO(Dish dish) {
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish, dishVO);
        return dishVO;
    }
} 